/*
 * @Author: LVGRAPE
 * @LastEditors: LVGRAPE
 */
#include "drv_pin.h"
#include "fc_state.h"
#include "rtthread.h"

const uint32_t gpio_pins[16] = {
    GPIO_PINS_0,
    GPIO_PINS_1,
    GPIO_PINS_2,
    GPIO_PINS_3,
    GPIO_PINS_4,
    GPIO_PINS_5,
    GPIO_PINS_6,
    GPIO_PINS_7,
    GPIO_PINS_8,
    GPIO_PINS_9,
    GPIO_PINS_10,
    GPIO_PINS_11,
    GPIO_PINS_12,
    GPIO_PINS_13,
    GPIO_PINS_14,
    GPIO_PINS_15,
};
gpio_init_type gpio_init_struct;
gpio_type *GPIO_PORTS[5] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOF};
crm_periph_clock_type GPIO_CLOCKS[5] = {CRM_GPIOA_PERIPH_CLOCK, CRM_GPIOB_PERIPH_CLOCK, CRM_GPIOC_PERIPH_CLOCK, CRM_GPIOD_PERIPH_CLOCK, CRM_GPIOF_PERIPH_CLOCK};
void at_pin_mode_od(gpio_type *port, uint32_t pins)
{
    gpio_init_struct.gpio_pins = pins;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init(port, &gpio_init_struct);
}
void at_pin_mode_pp(gpio_type *port, uint32_t pins)
{
    gpio_init_struct.gpio_pins = pins;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init(port, &gpio_init_struct);
}
void at_pin_mode_input(gpio_type *port, uint32_t pins)
{
    gpio_init_struct.gpio_pins = pins;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init(port, &gpio_init_struct);
}
void pin_mode(pin_index_t pin, pin_mode_type mode)
{

    gpio_default_para_init(&gpio_init_struct);

    gpio_type *GPIOx = GPIO_PORTS[pin / 16];
    crm_periph_clock_type clock = GPIO_CLOCKS[pin / 16];
    gpio_init_struct.gpio_pins = gpio_pins[pin % 16];
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MAXIMUM;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;

    // gpio_init_struct.gpio_pins = GPIO_PINS_ALL;
    // gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    // gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    // gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    // gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    switch (mode)
    {
    case PIN_MODE_INPUT_PULLUP:
        gpio_init_struct.gpio_pull = GPIO_PULL_UP;
        break;
    case PIN_MODE_INPUT_PULLDOWN:
        gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
        break;
    case PIN_MODE_OUTPUT_PP:
        gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
        break;
    case PIN_MODE_OUTPUT_OD:
        gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
        gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
        break;
    case PIN_MODE_MUX:
        gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
        break;
    case PIN_MODE_ANALOG:
        gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
        break;
    default:
        break;
    }
    crm_periph_clock_enable(clock, TRUE);
    gpio_init(GPIOx, &gpio_init_struct);

    // rt_kprintf("Port: %08X pin: %08X clk:%08X\n", GPIOx, gpio_init_struct.gpio_pins, clock);
}
gpio_type *pin_get_port(pin_index_t pin)
{
    return GPIO_PORTS[pin / 16];
}
uint32_t pin_get_pin(pin_index_t pin)
{
    return gpio_pins[pin % 16];
}
void pin_write(pin_index_t pin, confirm_state value)
{
    if (value)
        gpio_bits_set(GPIO_PORTS[pin / 16], gpio_pins[pin % 16]);
    else
        gpio_bits_reset(GPIO_PORTS[pin / 16], gpio_pins[pin % 16]);
}
pin_state pin_read(pin_index_t pin)
{
    return gpio_input_data_bit_read(GPIO_PORTS[pin / 16], gpio_pins[pin % 16]);
}

#define SHOW_TIME 32
#define MAX_DIN 255

uint8_t blinkSlowVal   = 0;
uint8_t blinkFastVal   = 0;
uint8_t blinkBreathVal = 0;
uint8_t blinkDotVal    = 0;

uint8_t blinkValues[RGB_STATE_MODE_CNT];
void generate_led_blink_value(void)
{
    static uint8_t ledCnt = 0;
    ledCnt++;
    if (ledCnt > SHOW_TIME) {
        ledCnt = 0;
    }

    blinkSlowVal   = 0;
    blinkFastVal   = 0;
    blinkBreathVal = 0;
    blinkDotVal    = 0;

    if ((ledCnt % (SHOW_TIME / 8)) < (SHOW_TIME / 16)) {
        blinkFastVal = MAX_DIN;
    }
    if (ledCnt < (SHOW_TIME / 2)) {
        blinkSlowVal = MAX_DIN;
    }

    if (ledCnt < (SHOW_TIME / 2)) {
        blinkBreathVal = MAX_DIN * ledCnt / (SHOW_TIME / 2);
    } else {
        blinkBreathVal = MAX_DIN * (SHOW_TIME - ledCnt) / (SHOW_TIME / 2);
    }

    if (ledCnt <= (SHOW_TIME / 2 + SHOW_TIME / 4) && ledCnt >= (SHOW_TIME / 2)) {
        if ((ledCnt % (SHOW_TIME / 4 / 2)) == 0) {
            blinkDotVal = MAX_DIN;
        }
    }

    // rt_kprintf("ledCnt: %3d, slow: %3d, fast: %3d, breath: %3d, dot: %3d\n", ledCnt, blinkSlowVal, blinkFastVal, blinkBreathVal, blinkDotVal);
    blinkValues[0] = blinkFastVal;
    blinkValues[1] = blinkSlowVal;
    blinkValues[2] = blinkBreathVal;
    blinkValues[3] = blinkDotVal;
    blinkValues[4] = 0;
    blinkValues[5] = MAX_DIN;
}
uint8_t get_blinkSlowVal(void)
{
    return blinkSlowVal;
}
uint8_t get_blinkFastVal(void)
{
    return blinkFastVal;
}
uint8_t get_blinkBreathVal(void)
{
    return blinkBreathVal;
}
uint8_t get_blinkDotVal(void)
{
    return blinkDotVal;
}
